package cn.source.system.common.Util;

import cn.hutool.core.util.ObjectUtil;
import cn.source.system.common.annotation.UpdateDataCompare;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtils;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * CompareObjUtils.java此类用于比较新老对象的差别
 * @author: YXZhou
 * @remark:
 */
@Slf4j
public class CompareObjUtils {

    /**
     * 比较新老对象的差别
     * @param newObj
     * @param oldObj
     * @return
     * @throws IllegalAccessException
     */
    public static Map<String, Object> compareObject(Object newObj, Object oldObj) {
        Map<String, Object> returnMap = new HashMap<>(8);

        StringBuilder oldValueContent = new StringBuilder();
        StringBuilder newValueContent = new StringBuilder();

        oldValueContent.append("{");
        newValueContent.append("{");
        if (oldObj != null && newObj != null) {
            Map<String, Object> oldMap = null;
            Map<String, Object> newMap = null;
            try {
                oldMap = changeValueToMap(oldObj);
                newMap = changeValueToMap(newObj);
            } catch (IllegalAccessException e) {
                log.error("比较新老对象的差别异常", e);
            }

            if (oldMap != null && !oldMap.isEmpty()) {
                for (Map.Entry<String, Object> oldEntry : oldMap.entrySet()) {
                    Object oldValue = oldEntry.getValue();
                    Object newValue = newMap.get(oldEntry.getKey());

                    // 旧值和新值不相等时
                    if (ObjectUtil.notEqual(oldValue, newValue)) {
                        oldValueContent.append("\""+ oldEntry.getKey() +"\"").append(":").append(oldValue).append(";");
                        newValueContent.append("\""+ oldEntry.getKey() +"\"").append(":").append(newValue).append(";");
                    }
                }
            }
        }
        oldValueContent.append("}");
        newValueContent.append("}");

        returnMap.put("oldValue", oldValueContent);
        returnMap.put("newValue", newValueContent);

        return returnMap;
    }


    /**
     * 将类对象转换成Map
     * @param entity 原对象
     * @return Map
     * @throws IllegalAccessException 类型转换时报错
     */
    private static Map<String, Object> changeValueToMap(Object entity) throws IllegalAccessException {
        Map<String, Object> resultMap = new HashMap<>(8);
        Field[] fields = entity.getClass().getDeclaredFields();
        for (Field field : fields) {
            String name = field.getName();
            if (PropertyUtils.isReadable(entity, name) && PropertyUtils.isWriteable(entity, name)) {
                if (field.isAnnotationPresent(UpdateDataCompare.class)) {
                    UpdateDataCompare anno = field.getAnnotation(UpdateDataCompare.class);
                    // 获取private对象字段值
                    field.setAccessible(true);
                    resultMap.put(anno.name(), field.get(entity));
                }
            }
        }
        return resultMap;
    }
}
